home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung 2 / Power-Programmierung CD 2 (Tewi)(1994).iso / gnu / gnulib / ghostscr / gdevvga.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-12-31  |  16.5 KB  |  638 lines

  1. /* Copyright (C) 1989, 1990 Aladdin Enterprises.  All rights reserved.
  2.    Distributed by Free Software Foundation, Inc.
  3.  
  4. This file is part of Ghostscript.
  5.  
  6. Ghostscript is distributed in the hope that it will be useful, but
  7. WITHOUT ANY WARRANTY.  No author or distributor accepts responsibility
  8. to anyone for the consequences of using it or for whether it serves any
  9. particular purpose or works at all, unless he says so in writing.  Refer
  10. to the Ghostscript General Public License for full details.
  11.  
  12. Everyone is granted permission to copy, modify and redistribute
  13. Ghostscript, but only under the conditions described in the Ghostscript
  14. General Public License.  A copy of this license is supposed to have been
  15. given to you along with Ghostscript so you can know your rights and
  16. responsibilities.  It should be in a file named COPYING.  Among other
  17. things, the copyright notice and this notice must be preserved on all
  18. copies.  */
  19.  
  20. /* gdevegad(ir).c */
  21. /* EGA driver for Ghostscript using direct access to frame buffer */
  22. #define GS_EGA_DEVICE gs_ega_device
  23. #define DEVICE_NAME "ega"
  24. #include "gdevega.h"
  25. #define USE_ASM 1            /* use assembly language */
  26.  
  27. /* Type and macro for frame buffer pointers. */
  28. /* Note: requires (raster_x & 15) == 0. */
  29. /*** Intimately tied to the 80x86 (x<2) addressing architecture. ***/
  30. typedef byte far *fb_ptr;
  31. #define mk_fb_ptr(x, y)\
  32.   ((fb_ptr)MK_FP(regen + (y) * (raster_x >> 4), (x) >> 3))
  33. /* Define the largest height that can be processed */
  34. /* within a single 64K segment.  If screen_size_y > max_rop_height, */
  35. /* we may have to break up operations into pieces. */
  36. #define max_rop_height (0xffff / raster_x)
  37.  
  38. /* Structure for operation parameters. */
  39. /* Note that this structure is known to assembly code. */
  40. /* Not all parameters are used for every operation. */
  41. typedef struct rop_params_s {
  42.     fb_ptr dest;            /* pointer to frame buffer */
  43.     int draster;            /* raster of frame buffer */
  44.     byte far *src;            /* pointer to source data */
  45.     int sraster;            /* source raster */
  46.     int width;            /* width in bytes */
  47.     int height;            /* height in scan lines */
  48.     int shift;            /* amount to right shift source */
  49.     int invert;            /* 0 or -1 to invert source */
  50.     int data;            /* data for fill */
  51. } rop_params;
  52. typedef rop_params _ss *rop_ptr;
  53.  
  54. /* Assembly language routines */
  55.  
  56. #if USE_ASM
  57. void memsetcol(P1(rop_ptr)); /* dest, draster, height, data */
  58. #else
  59. #define memsetcol cmemsetcol
  60. private void
  61. cmemsetcol(rop_ptr rop)
  62. {    byte far *addr = rop->dest;
  63.     int yc = rop->height;
  64.     while ( yc-- )
  65.      { byte discard = *addr;
  66.        *addr = rop->data;
  67.        addr += rop->draster;
  68.      }
  69. }
  70. #endif
  71.  
  72. #if USE_ASM
  73. void memsetrect(P1(rop_ptr)); /* dest, draster, width, height, data */
  74. #else
  75. #define memsetrect cmemsetrect
  76. private void
  77. cmemsetrect(rop_ptr rop)
  78. {    byte far *addr = rop->dest;
  79.     int yc = rop->height;
  80.     while ( yc-- )
  81.      { int cnt = rop->width;
  82.        while ( cnt-- ) *addr++ = rop->data;
  83.        addr += rop->draster - rop->width;
  84.      }
  85. }
  86. #endif
  87.  
  88. #if USE_ASM
  89. void memrwcol(P1(rop_ptr)); /* dest, draster, src, sraster, height, shift, invert */
  90. #else
  91. #define memrwcol cmemrwcol
  92. private void
  93. cmemrwcol(rop_ptr rop)
  94. {    byte far *dp = rop->dest, *sp = rop->src;
  95.     int yc = rop->height;
  96.     int shift = rop->shift;
  97.     while ( yc-- )
  98.      { byte discard = *dp;
  99.        *dp = ((*sp >> shift) + (*sp << (8 - shift))) ^ rop->invert;
  100.        dp += rop->draster, sp += rop->sraster;
  101.      }
  102. }
  103. #endif
  104.  
  105. #if USE_ASM
  106. void memrwcol2(P1(rop_ptr)); /* dest, draster, src, sraster, height, shift, invert */
  107. #else
  108. #define memrwcol2 cmemrwcol2
  109. private void
  110. cmemrwcol2(rop_ptr rop)
  111. {    byte far *dp = rop->dest, *sp = rop->src;
  112.     int yc = rop->height;
  113.     int shift = rop->shift;
  114.     while ( yc-- )
  115.      { byte discard = *dp;
  116.        *dp = ((sp[1] >> shift) + (*sp << (8 - shift))) ^ rop->invert;
  117.        dp += rop->draster, sp += rop->sraster;
  118.      }
  119. }
  120. #endif
  121.  
  122. /* Forward definitions */
  123. void fill_rectangle(P4(rop_ptr, int, int, int));
  124.  
  125. /* Define the device port and register numbers, and the regen map base */
  126. #define out2(port, index, data)\
  127.   (outportb(port, index), outportb((port)+1, data))
  128. #define seq_addr 0x3c4
  129. #define s_map 2
  130. #define set_s_map(mask) out2(seq_addr, s_map, mask)
  131. #define graph_addr 0x3ce
  132. #define g_const 0            /* set/reset */
  133. #define set_g_const(color) out2(graph_addr, g_const, color)
  134. #define g_const_map 1            /* enable set/reset */
  135. #define set_g_const_map(map) out2(graph_addr, g_const_map, map)
  136. #define g_function 3
  137. #define set_g_function(func) out2(graph_addr, g_function, func)
  138. #  define gf_WRITE 0
  139. #  define gf_AND 8
  140. #  define gf_OR 0x10
  141. #  define gf_XOR 0x18
  142. #define g_mode 5
  143. #define set_g_mode(mode) out2(graph_addr, g_mode, mode)
  144. #  define gm_DATA 0
  145. #  define gm_FILL 2
  146. #define g_mask 8
  147. #define set_g_mask(mask) out2(graph_addr, g_mask, mask)
  148. #define regen 0xa000
  149.  
  150. /* Clean up after writing */
  151. #define dot_end()\
  152.   set_g_mask(0xff)            /* all bits on */
  153.  
  154. /* Initialize the EGA for graphics mode */
  155. int
  156. ega_open(gx_device *dev)
  157. {    if ( ega_save_mode < 0 ) ega_save_mode = ega_get_mode();
  158.     ega_set_mode(graphics_video_mode);
  159.     set_s_map(-1);            /* enable all maps */
  160.     return 0;
  161. }
  162.  
  163. /* Write a dot using the EGA color codes. */
  164. /* This doesn't have to be efficient. */
  165. int
  166. ega_write_dot(gx_device *dev, int x, int y, gx_color_index color)
  167. {    byte data = (byte)color;
  168.     return ega_copy_color(dev, &data, 1, 1, x, y, 1, 1);
  169. }
  170.  
  171. /* Macro for testing bit-inclusion */
  172. #define bit_included_in(x,y) !((x)&~(y))
  173.  
  174. /* Copy a monochrome bitmap.  The colors are given explicitly. */
  175. /* Color = gx_no_color_index means transparent (no effect on the image). */
  176. int
  177. ega_copy_mono(gx_device *dev, byte *base, int sourcex, int raster,
  178.   int x, int y, int w, int h, gx_color_index izero, gx_color_index ione)
  179. {    rop_params params;
  180. #define czero (int)izero
  181. #define cone (int)ione
  182.     int dleft, count;
  183.     byte mask, rmask;
  184.     fb_ptr save_dest;
  185.     int other_color = -1;
  186.     validate_rect();
  187. #if screen_size_y > max_rop_height
  188.     while ( h > max_rop_height )
  189.        {    int code = ega_copy_mono(dev, base, sourcex, raster,
  190.                 x, y, w, max_rop_height, izero, ione);
  191.         if ( code != 0 ) return code;
  192.         base = (byte *)((byte huge *)base +
  193.                 raster * (long)max_rop_height);
  194.         y += max_rop_height;
  195.         h -= max_rop_height;
  196.        }
  197. #endif
  198.     params.dest = mk_fb_ptr(x, y);
  199.     params.draster = raster_x;
  200.     params.src = base + (sourcex >> 3);
  201.     params.sraster = raster;
  202.     params.height = h;
  203.     params.shift = (x - sourcex) & 7;
  204.     /* Analyze the 16 possible cases: each of izero and ione may be */
  205.     /* 0, 0xf, transparent, or some other color. */
  206.     switch ( czero )
  207.        {
  208.     case no_color:
  209.         switch ( cone )
  210.            {
  211.         default:        /* (T, other) */
  212.             /* Must do 2 passes */
  213.             other_color = cone;
  214.             save_dest = params.dest;
  215.             /* falls through */
  216.         case 0:            /* (T, 0) */
  217.             set_g_function(gf_AND);
  218.             params.invert = -1;
  219.             break;
  220.         case 0xf:        /* (T, 0xf) */
  221.             set_g_function(gf_OR);
  222.             params.invert = 0;
  223.             break;
  224.         case no_color:        /* (T, T) */
  225.             return 0;    /* nothing to do */
  226.            }
  227.         break;
  228.     case 0:
  229.         params.invert = 0;
  230.         switch ( cone )
  231.            {
  232.         default:        /* (0, other) */
  233.             set_g_const(0);
  234.             set_g_const_map(cone ^ 0xf);
  235.             /* falls through */
  236.         case 0xf:        /* (0, 0xf) */
  237.             break;
  238.         case no_color:        /* (0, T) */
  239.             set_g_function(gf_AND);
  240.             break;
  241.            }
  242.         break;
  243.     case 0xf:
  244.         params.invert = -1;
  245.         switch ( cone )
  246.            {
  247.         case 0:            /* (0xf, 0) */
  248.             break;
  249.         default:        /* (0xf, other) */
  250.             set_g_const(0xf);
  251.             set_g_const_map(cone);
  252.             break;
  253.         case no_color:        /* (0xf, T) */
  254.             set_g_function(gf_OR);
  255.             /* falls through */
  256.            }
  257.         break;
  258.     default:
  259.         switch ( cone )
  260.            {
  261.         default:        /* (other, not T) */
  262.             if ( bit_included_in(czero, cone) )
  263.                {    set_g_const(czero);
  264.                 set_g_const_map(czero ^ cone ^ 0xf);
  265.                 params.invert = 0;
  266.                 break;
  267.                }
  268.             else if ( bit_included_in(cone, czero) )
  269.                {    set_g_const(cone);
  270.                 set_g_const_map(cone ^ czero ^ 0xf);
  271.                 params.invert = -1;
  272.                 break;
  273.                }
  274.             /* No way around it, fill with one color first. */
  275.             save_dest = params.dest;
  276.             fill_rectangle((rop_ptr)¶ms, x & 7, w, cone);
  277.             params.dest = save_dest;
  278.             set_g_function(gf_XOR);
  279.             set_s_map(czero ^ cone);
  280.             other_color = -2;    /* must reset s_map at end */
  281.             params.invert = -1;
  282.             break;
  283.         case no_color:        /* (other, T) */
  284.             /* Must do 2 passes */
  285.             other_color = czero;
  286.             save_dest = params.dest;
  287.             set_g_function(gf_AND);
  288.             params.invert = 0;
  289.             break;
  290.            }
  291.         break;
  292.        }
  293.     /* Actually copy the bits. */
  294.     dleft = 8 - (x & 7);
  295.     mask = 0xff >> (8 - dleft);
  296.     count = w - dleft;
  297.     if ( count < 0 )
  298.         mask -= mask >> w,
  299.         rmask = 0;
  300.     else
  301.         rmask = 0xff00 >> (count & 7);
  302.     /* params: dest, src, sraster, height, shift, invert */
  303.     /* Smashes params.src, params.dest, count. */
  304. copy:    set_g_mask(mask);
  305.     if ( params.shift == 0 )    /* optimize the aligned case */
  306.        {    /* Do left column */
  307.         memrwcol((rop_ptr)¶ms);
  308.         /* Do center */
  309.         if ( (count -= 8) >= 0 )
  310.            {    set_g_mask(0xff);
  311.             do
  312.                {    params.src++, params.dest++;
  313.                 memrwcol((rop_ptr)¶ms);
  314.                }
  315.             while ( (count -= 8) >= 0 );
  316.            }
  317.         /* Do right column */
  318.         if ( rmask )
  319.            {    params.src++, params.dest++;
  320.             set_g_mask(rmask);
  321.             memrwcol((rop_ptr)¶ms);
  322.            }
  323.        }
  324.     else
  325.        {    /* Do left column */
  326.         int sleft = 8 - (sourcex & 7);
  327.         if ( sleft >= dleft )
  328.            {    /* Source fits in one byte */
  329.             memrwcol((rop_ptr)¶ms);
  330.            }
  331.         else if ( w <= sleft )
  332.            {    /* Source fits in one byte, thin case */
  333.             memrwcol((rop_ptr)¶ms);
  334.             goto fin;
  335.            }
  336.         else
  337.            {    memrwcol2((rop_ptr)¶ms);
  338.             params.src++;
  339.            }
  340.         /* Do center */
  341.         if ( (count -= 8) >= 0 )
  342.            {    set_g_mask(0xff);
  343.             do
  344.                {    params.dest++;
  345.                 memrwcol2((rop_ptr)¶ms);
  346.                 params.src++;
  347.                }
  348.             while ( (count -= 8) >= 0 );
  349.            }
  350.         /* Do right column */
  351.         if ( rmask )
  352.            {    set_g_mask(rmask);
  353.             params.dest++;
  354.             if ( count + 8 <= params.shift )
  355.                 memrwcol((rop_ptr)¶ms);
  356.             else
  357.                 memrwcol2((rop_ptr)¶ms);
  358.            }
  359.        }
  360. fin:    if ( other_color != -1 )
  361.        {    if ( other_color >= 0 )
  362.            {    /* Do the second pass on (T, other) or (other, T). */
  363.             count = w - dleft;
  364.             params.src = base + (sourcex >> 3);
  365.             params.dest = save_dest;
  366.             params.invert ^= -1;
  367.             set_s_map(other_color);
  368.             set_g_function(gf_OR);
  369.             other_color = -2;
  370.             goto copy;
  371.            }
  372.         else
  373.            {    /* Finished second pass, restore s_map */
  374.             set_s_map(-1);
  375.            }
  376.        }
  377.     set_g_function(gf_WRITE);
  378.     set_g_const_map(0);
  379.     dot_end();
  380.     return 0;
  381. #undef czero
  382. #undef cone
  383. }
  384.  
  385. /* Copy a color pixelmap.  This is just like a bitmap, */
  386. /* except that each pixel takes 4 bits instead of 1. */
  387. int
  388. ega_copy_color(gx_device *dev, byte *base, int sourcex, int raster,
  389.   int x, int y, int w, int h)
  390. {    byte *line = base + (sourcex >> 1);
  391.     unsigned lmask = 0x80 >> (x & 7);
  392.     int bitx = sourcex & 1;
  393.     int ex = w + bitx;
  394.     fb_ptr fbline;
  395.     validate_rect();
  396. #if screen_size_y > max_rop_height
  397.     while ( h > max_rop_height )
  398.        {    int code = ega_copy_color(dev, base, sourcex, raster,
  399.                 x, y, w, max_rop_height);
  400.         if ( code != 0 ) return code;
  401.         base = (byte *)((byte huge *)base +
  402.                 raster * (long)max_rop_height);
  403.         y += max_rop_height;
  404.         h -= max_rop_height;
  405.        }
  406. #endif
  407.     fbline = mk_fb_ptr(x, y);
  408.     set_g_mode(gm_FILL);
  409.     outportb(graph_addr, g_mask);    /* first half of set_g_mask */
  410.     while ( --h >= 0 )
  411.     {    byte *bptr = line;
  412.         int px = bitx;
  413.         /* Turbo C will put an unsigned in a register, */
  414.         /* but not a byte! */
  415.         register unsigned mask = lmask;
  416.         fb_ptr fbptr = fbline;
  417.         do
  418.            {    byte discard = *fbptr;    /* latch frame buffer data */
  419.             outportb(graph_addr+1, mask);    /* 2nd half of set_g_mask */
  420.             *fbptr = (px & 1 ? *bptr++ : *bptr >> 4);
  421.             if ( (mask >>= 1) == 0 )
  422.                 mask = 0x80, fbptr++;
  423.            }
  424.         while ( ++px < ex );
  425.         line += raster;
  426.         fbline += raster_x;
  427.     }
  428.     set_g_mode(gm_DATA);
  429.     dot_end();
  430.     return 0;
  431. }
  432.  
  433. /* Fill a rectangle. */
  434. int
  435. ega_fill_rectangle(gx_device *dev, int x, int y, int w, int h,
  436.   gx_color_index color)
  437. {    rop_params params;
  438.     validate_rect();
  439. #if screen_size_y > max_rop_height
  440.     while ( h > max_rop_height )
  441.        {    int code = ega_fill_rectangle(dev,
  442.             x, y, w, max_rop_height, color);
  443.         if ( code != 0 ) return code;
  444.         y += max_rop_height;
  445.         h -= max_rop_height;
  446.        }
  447. #endif
  448.     params.dest = mk_fb_ptr(x, y);
  449.     params.draster = raster_x;
  450.     params.height = h;
  451.     fill_rectangle((rop_ptr)¶ms, x & 7, w, (int)color);
  452.     dot_end();
  453.     return 0;
  454. }
  455.  
  456. /* Tile a rectangle.  Note that the two colors must both be supplied, */
  457. /* i.e. neither one can be gx_no_color_index (transparent): */
  458. /* a transparent color means that the tile is colored, not a mask. */
  459. int
  460. ega_tile_rectangle(gx_device *dev, gx_bitmap *tile,
  461.   int x, int y, int w, int h, gx_color_index czero, gx_color_index cone)
  462. #define zero (int)czero
  463. #define one (int)cone
  464. {    rop_params params;
  465.     int xmod, width_bytes;
  466.     int tile_height = tile->height;
  467.     int xbit;
  468.     int lcount;
  469.     int mask, rmask;
  470.     byte narrow;
  471.     byte again;
  472.     int const_bits, maps;
  473.     int ymod, yleft;
  474. #if screen_size_y > max_rop_height
  475.     while ( h > max_rop_height )
  476.        {    int mod_height = max_rop_height / tile_height * tile_height;
  477.         int code = ega_tile_rectangle(dev, tile,
  478.             x, y, w, mod_height, czero, cone);
  479.         if ( code != 0 ) return code;
  480.         y += mod_height;
  481.         h -= mod_height;
  482.        }
  483. #endif
  484.     if ( tile->width & 7 ) return -1;    /* can't do it */
  485.     if ( one == -1 || zero == -1 ) return -1;    /* can't do colors */
  486.     /* Following is similar to aligned case of copy_mono */    
  487.     validate_rect();
  488.     params.dest = mk_fb_ptr(x, y);
  489.     params.draster = raster_x;
  490.     params.sraster = tile->raster;
  491.     params.shift = 0;
  492.     xbit = x & 7;
  493.     /* Set up the graphics registers */
  494.     const_bits = (zero ^ one) ^ 0xf;
  495.     if ( const_bits )
  496.        {    set_g_const(zero);    /* either color will do */
  497.         set_g_const_map(const_bits);
  498.        }
  499.     if ( (maps = zero & ~one) != 0 )
  500.        {    set_s_map(maps += const_bits);
  501.         params.invert = -1;
  502.         again = one & ~zero;
  503.        }
  504.     else
  505.        {    maps = one & ~zero;
  506.         set_s_map(maps += const_bits);
  507.         params.invert = 0;
  508.         again = 0;
  509.        }
  510.     xmod = (x % tile->width) >> 3;
  511.     width_bytes = tile->width >> 3;
  512.     mask = 0xff >> xbit;
  513.     if ( w + xbit <= 8 )
  514.         mask -= mask >> w,
  515.         rmask = 0,
  516.         narrow = 1;
  517.     else
  518.         rmask = (0xff00 >> ((w + x) & 7)) & 0xff,
  519.         w += xbit - 8,
  520.         narrow = 0;
  521.     ymod = y % tile_height;
  522. tile:    yleft = tile_height - ymod;
  523.     params.src = tile->data + ymod * params.sraster + xmod;
  524.     lcount = h;
  525.     if ( narrow )            /* Optimize narrow case */
  526.        {    set_g_mask(mask);
  527.         if ( lcount > yleft )
  528.            {    params.height = yleft;
  529.             memrwcol((rop_ptr)¶ms);
  530.             params.dest += yleft * raster_x;
  531.             params.src = tile->data + xmod;
  532.             params.height = tile_height;
  533.             lcount -= yleft;
  534.             while ( lcount >= tile_height )
  535.                {    memrwcol((rop_ptr)¶ms);
  536.                 params.dest += tile_height * raster_x;
  537.                 lcount -= tile_height;
  538.                }
  539.            }
  540.         if ( lcount )
  541.            {    params.height = lcount;
  542.             memrwcol((rop_ptr)¶ms);
  543.            }
  544.        }
  545.     else
  546.        {    fb_ptr line = params.dest;
  547.         while ( 1 )
  548.            {    int xoff = xmod;
  549.             int count = w;
  550.             params.height = (lcount > yleft ? yleft : lcount);
  551.             /* Do first byte */
  552.             set_g_mask(mask);
  553.             memrwcol((rop_ptr)¶ms);
  554.             /* Do full bytes */
  555.             if ( (count -= 8) >= 0 )
  556.                {    set_g_mask(0xff);
  557.                 do
  558.                    {    if ( ++xoff == width_bytes )
  559.                         xoff = 0,
  560.                         params.src -= params.sraster;
  561.                     ++params.src, ++params.dest;
  562.                     memrwcol((rop_ptr)¶ms);
  563.                    }
  564.                 while ( (count -= 8) >= 0 );
  565.                }
  566.             /* Do last byte */
  567.             if ( rmask )
  568.                {    if ( ++xoff == width_bytes )
  569.                     xoff = 0,
  570.                     params.src -= params.sraster;
  571.                 set_g_mask(rmask);
  572.                 ++params.src, ++params.dest;
  573.                 memrwcol((rop_ptr)¶ms);
  574.                }
  575.             if ( (lcount -= params.height) == 0 ) break;
  576.             params.dest = line += params.height * raster_x;
  577.             params.src = tile->data + xmod;
  578.             yleft = tile_height;
  579.            }
  580.        }
  581.     /* Now do the second color if needed */
  582.     if ( again )
  583.        {    maps = again + const_bits;
  584.         set_s_map(maps);
  585.         again = 0;
  586.         params.dest = mk_fb_ptr(x, y);
  587.         params.invert = 0;
  588.         goto tile;
  589.        }
  590.     if ( maps != 0xf )
  591.         set_s_map(-1);
  592.     if ( const_bits )
  593.         set_g_const_map(0);
  594.     dot_end();
  595.     return 0;
  596. }
  597.  
  598. /* ------ Internal routines ------ */
  599.  
  600. /* Fill a rectangle specified by pointer into frame buffer, */
  601. /* starting bit within byte, width, and height. */
  602. /* Smashes rop->dest. */
  603. private void
  604. fill_rectangle(register rop_ptr rop, int bit, int w, int color)
  605.   /* rop: dest, draster, height */
  606. {    static byte rmask_tab[9] =
  607.        {    0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff
  608.        };
  609.     set_g_const(color);
  610.     set_g_const_map(0xf);
  611.     if ( bit + w <= 8 )
  612.        {    /* Less than one byte */
  613.         set_g_mask(rmask_tab[w] >> bit);
  614.         memsetcol(rop);
  615.        }
  616.     else
  617.        {    int byte_count;
  618.         byte right_mask;
  619.         if ( bit )
  620.            {    set_g_mask(0xff >> bit);
  621.             memsetcol(rop);
  622.             rop->dest++;
  623.             w += bit - 8;
  624.            }
  625.         if ( (byte_count = w >> 3) != 0 )
  626.            {    set_g_mask(0xff);    /* all bits */
  627.             rop->width = byte_count;
  628.             memsetrect(rop);
  629.             rop->dest += byte_count;
  630.            }
  631.         if ( (right_mask = rmask_tab[w & 7]) != 0 )
  632.            {    set_g_mask(right_mask);
  633.             memsetcol(rop);
  634.            }
  635.        }
  636.     set_g_const_map(0);
  637. }
  638.